package com.shijie.sjoj.model.component;

import com.shijie.sjoj.model.constant.RedisKeyConstant;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.StringRedisTemplate;

import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.time.format.DateTimeFormatter;

/**
 * redis全局id生成器（64位）
 *
 * @author ZSJ
 */
@Slf4j
public class IdGeneratorRedis {

    /**
     * redis源
     */
    private final StringRedisTemplate stringRedisTemplate;

    /**
     * 用于生成的开始秒级Unix时间戳（32位）：2025-01-01T08:00:00
     */
    private static final long BEGIN_TIMESTAMP_SECOND = 1735718400L;

    /**
     * 序列号位数（时间戳移动位数）：32位
     */
    private static final short COUNT_BITS = 32;

/*
    // 初始化
    static {
        BEGIN_TIMESTAMP_SECOND = LocalDateTime.parse("2025-01-01T08:00:00").toEpochSecond(ZoneOffset.UTC);
        COUNT_BITS = 32;
    }
*/

    /**
     * 构造函数，可用于bean注入（构造注入）
     *
     * @param stringRedisTemplate StringRedisTemplate
     */
    public IdGeneratorRedis(StringRedisTemplate stringRedisTemplate) {
        if (null == stringRedisTemplate) {
            log.error("--- RedisIdGenerator: The StringRedisTemplate is null ---");
        }
        this.stringRedisTemplate = stringRedisTemplate;
    }

    /**
     * 生成64位（时间戳32位，序列号32位）唯一id
     *
     * @param keyPrefix String
     * @return long
     */
    public long nextId(String keyPrefix) {
        // 获取当前日期时间信息
        LocalDateTime now = LocalDateTime.now();
        // 生成秒级Unix时间戳
        long timestamp = now.toEpochSecond(ZoneOffset.UTC) - BEGIN_TIMESTAMP_SECOND;
        // 获取当前日期到天（redis存储键）
        String date = now.format(DateTimeFormatter.ofPattern("yyyy:MM:dd"));
        // 获取自增长序列号
        Long count = stringRedisTemplate.opsForValue().increment("increment_id:" + keyPrefix + ":" + date);
        // 位运算拼接生成全局ID，时间戳+序列号
        return timestamp << COUNT_BITS | (null == count ? 1L : count);
    }

    /**
     * 生成题目id
     *
     * @return Long
     */
    public final Long nextQuizId() {
        return this.nextId(RedisKeyConstant.QUIZ_KEY_PREFIX);
    }

    /**
     * 生成用户id
     *
     * @return Long
     */
    public final Long nextUserId() {
        return this.nextId(RedisKeyConstant.USER_KEY_PREFIX);
    }

    /**
     * 生成记录id
     *
     * @return Long
     */
    public final Long nextRecordId() {
        return this.nextId(RedisKeyConstant.RECORD_KEY_PREFIX);
    }


}
